#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "ini_operation.h"

static pthread_mutex_t g_ini_file_rw_mutex = PTHREAD_MUTEX_INITIALIZER;

int read_ini_num(const char* s_variant, const char *filename, int * value)
{
	if(NULL == value)
	{
		return -1;
	}

	char buf[LINE_LENGTH] = {0};
	if(0 != read_ini_str(s_variant, filename, buf))
	{
		return -1;
	}
	*value = atoi(buf);

	return 0;
}

int read_ini_str(const char* s_variant, const char *filename, char * out_value)
{
	int name_len = strlen(s_variant);
	if(NULL == filename || NULL == s_variant || NULL == out_value || name_len >= LINE_LENGTH - 2)
	{
		return -1;
	}

	FILE* flp = fopen(filename, "r");
	if(NULL == flp)
	{
		//printf("read_ini_str: open ini file %s failed\n", filename);
		return -1;
	}

	int ret = -1;
	char buffer[LINE_LENGTH] = {0};
	while(NULL != fgets(buffer, LINE_LENGTH, flp))
	{
		if(0 == strncmp(buffer, s_variant, name_len))
		{
			if(buffer[name_len] != '=')
				continue;

			char * buffer_value = &buffer[name_len+1];
			while (*buffer_value != ' ' && *buffer_value != '\r' && *buffer_value != '\n' && *buffer_value != '\0')	//不复制空格(空格都在buffer_value的尾部)
			{
				*out_value = *buffer_value;
				++out_value;
				++buffer_value;
			}
			*(out_value) = '\0';

			ret = 0;
			break;
		}
	}

	fclose(flp);

	if(ret < 0)
	{
		//printf("read_ini_str: can not find item:%s\n", s_variant);
	}

	return ret;
}


int modify_ini(const char *s_variant, char *s_value, const char* ini_file_path)
{
	if(NULL == ini_file_path || NULL == s_variant || NULL == s_value)
	{
		return -1;
	}

	int l, i;
	//Skip the space at the begin
	l = strlen(s_value);
	for(i = 0; i < l; i++){
		if(*s_value != ' ')
			break;
		s_value++;
	}
	//Skip the space at the end
	l = strlen(s_value);
	for(i = l - 1; i >= 0; i--){
		if(s_value[i] != ' ')
			break;
		s_value[i] = 0;
	}

	if(strlen(s_variant) + 1 + strlen(s_value) + 1 >= LINE_LENGTH) // '=' and '\n' need space
	{
		return -1;
	}

	pthread_mutex_lock(&g_ini_file_rw_mutex);

	//Create the ini file if the file does not exist.
	FILE *flp = fopen(ini_file_path, "r+");
	if (flp == NULL)
	{
		flp = fopen(ini_file_path, "w+");
		if(NULL == flp)
		{
			//perror("open modify file error \n");
			pthread_mutex_unlock(&g_ini_file_rw_mutex);
			return -1;
		}
	}
	fseek(flp, 0, SEEK_SET);

	char buffer[LINE_LENGTH] = {0};
	char modify_buffer[LINE_LENGTH] = {0};

	int name_len = strlen(s_variant);
	int have_item = 0;
	int is_successful = 0;

	while(NULL != fgets(buffer, LINE_LENGTH, flp))
	{
		//buffer should contains '\n'
		if( 0 == strncmp(buffer, s_variant, name_len))
		{
			if(buffer[name_len] != '=')
				continue;

			have_item = 1;

			//复制参数名和'='到modify_buffer中
			strncpy(modify_buffer, buffer, name_len+1);
			//把值连接到modify_buffer末尾
			strcat(modify_buffer, s_value);

			int modify_buffer_len = strlen(modify_buffer);
			int buffer_len = strlen(buffer);
			if(modify_buffer_len <= buffer_len - 1)
			{
				//There is no need to move other configuration items
				int i = 0;
				for(i = modify_buffer_len; i < buffer_len - 1; i++)
				{
					modify_buffer[i] = ' ';
				}
				modify_buffer[i] = '\n';
				fseek(flp, -buffer_len , SEEK_CUR);
				is_successful = fwrite(modify_buffer, sizeof(char), buffer_len, flp);
			}
			else
			{
				int copy_start = ftell(flp);
				fseek(flp, 0, SEEK_END);
				int copy_end = ftell(flp);
				int copy_cnt = copy_end - copy_start;

				char* next_buffer = (char*)malloc(copy_cnt);
				if(next_buffer == NULL)
				{
					is_successful = -1;
					break;
				}
				memset(next_buffer, 0, copy_cnt);
				fseek(flp, -copy_cnt , SEEK_END);
				fread(next_buffer, 1, copy_cnt, flp);

				//返回到读入相同参数名的位置,在这里重写修改后的参数
				fseek(flp, -(buffer_len + copy_cnt) , SEEK_CUR);
				strcat(modify_buffer, "\n");
				is_successful = fwrite(modify_buffer, sizeof(char), strlen(modify_buffer), flp);
				is_successful = fwrite(next_buffer, sizeof(char), copy_cnt, flp);
				free(next_buffer);
			}

			break;
		}

		memset(buffer, 0, LINE_LENGTH);
	}

	//没有找到同名参数,则在配置文件尾加上这个新参数
	if(0 == have_item)
	{
		memset(modify_buffer, 0, LINE_LENGTH);
		strcpy(modify_buffer, s_variant);
		strncat(modify_buffer, "=", 1);
		strcat(modify_buffer, s_value);
		strcat(modify_buffer, "\n");
		is_successful = fwrite(modify_buffer, sizeof(char), strlen(modify_buffer), flp);
	}

	fclose(flp);
	flp = NULL;

	pthread_mutex_unlock(&g_ini_file_rw_mutex);
	system("sync");
	if( 0 > is_successful)
	{
		//printf("modify value error !\n");
		return -1;
	}

	return 0;
}
